package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    /**
     * 加入购物车
     * @param skuId
     * @param userId
     * @param skuNum
     */
    @Override
    public void addToCart(Long skuId, String userId, Long skuNum) {
 /*
        1.  先判断当前购物车中是否有该商品！
            true：
                有这个商品，数量相加  更新数据
            false:
                直接插入数据
*/
        //  分析使用哪个数据类型，以及key hash 结构： hset key field value  key=user:userId:cart field = skuId  value = cartInfo;
        //  hget key field; 获取购物车中的单个购物项    hvals key;  查看购物车列表！
        String cartKey = getCartKey(userId);
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        //判断
        if (cartInfoExist!=null){
            //更新数据
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum()+skuNum.intValue());
            //查询一下最新的实时价格
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //细节
            cartInfoExist.setIsChecked(1);
            cartInfoExist.setUpdateTime(new Date());
        }else {
            //插入数据
            CartInfo cartInfo = new CartInfo();
            //赋值操作
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfo.setSkuPrice(skuInfo.getPrice());
            cartInfo.setCartPrice(skuInfo.getPrice());
            cartInfo.setSkuNum(skuNum.intValue());
            cartInfo.setSkuId(skuId);
            cartInfo.setUserId(userId);
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
            cartInfoExist=cartInfo;
        }
        //放入缓存    hset key filed values       key = cartKey    filed = skuId     values=cartInfoExist
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        //如果要是有过期时间的话
        //setCartKeyExpire(cartKey);
    }

    /**
     * 展示购物车
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
         /*
            1.  判断是否登录，根据判断结果查询不同的购物车！
            2.  查询的结果需要排序！
            3.  有可能需要合并！

            情况1  只有 userTempId
            情况2  只有 userId
            情况3  有俩个   userId   userTempId
         */
        List<CartInfo> onLoginCartInfoList = null;
        List<CartInfo> loginCartInfoList = null;
        //属于未登录         情况1
        if (!StringUtils.isEmpty(userTempId)){
            String cartKey = this.getCartKey(userTempId);
            //获取登录的购物车集合数据！
            onLoginCartInfoList=this.redisTemplate.opsForHash().values(cartKey);
        }

        if (StringUtils.isEmpty(userId)){
            //排序：京东按照更新时间   苏宁按照创建时间
            List<CartInfo> onLoginCartInfoListLast = onLoginCartInfoList.stream().sorted((o1, o2) -> {
                //按照更新时间
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            }).collect(Collectors.toList());
            //返回购物车列表
            return onLoginCartInfoListLast;
        }

        //属于登录
        //登录的key
        String cartKey = this.getCartKey(userId);
        //这是登录状态下的购物车列表
        BoundHashOperations<String, String, CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);  // hvals key
            if (!CollectionUtils.isEmpty(onLoginCartInfoList)){

                onLoginCartInfoList.stream().forEach(cartInfo -> {
                    //比较skuid   如何skuid相等说明需要合并
                    if (boundHashOperations.hasKey(cartInfo.getSkuId().toString())){
                        //是有同一个skuid商品的情况
                        //业务逻辑   skunum   +  更新时间
                        //  hset key field value;  hget key field;  hvals key ; hmset key field value field value;  hmset key map;
                        CartInfo loginCartInfo = boundHashOperations.get(cartInfo.getSkuId().toString());   //hget key field;
                        loginCartInfo.setSkuNum(loginCartInfo.getSkuNum()+cartInfo.getSkuNum());
                        loginCartInfo.setUpdateTime(new Date());
                        //最新的价格
                        loginCartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));

                        //选择状态合并     存在俩种情况
                        /**
                         *   未登录           1       1       0       0
                         *   已登录           0       1       0       1
                         *   合并后           1       1       0       1
                         */
                        //外层判断是为了过滤出未登录购物车中已选择的
                        if (cartInfo.getIsChecked()==1){
                            //内层判断是为了  节约操作   如果已经为选择     就不需要再次添加
                            if (loginCartInfo.getIsChecked()==0){
                                loginCartInfo.setIsChecked(1);
                            }
                        }
                        //修改缓存中的值
                        boundHashOperations.put(cartInfo.getSkuId().toString(),loginCartInfo);
                    }else {
                        //这个skuid商品情况不一样            直接添加
                        cartInfo.setUserId(userId);
                        cartInfo.setUpdateTime(new Date());
                        cartInfo.setCreateTime(new Date());
                        boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
                    }

                });
                //需要删除未登录购物车数据
                   this.redisTemplate.delete(this.getCartKey(userTempId));
            }

        loginCartInfoList = this.redisTemplate.boundHashOps(cartKey).values();
        //判断是否为空
        if (CollectionUtils.isEmpty(loginCartInfoList)){
            ArrayList<CartInfo> cartInfos = new ArrayList<>();
            return cartInfos;
        }
        //设置最后排序
        List<CartInfo> loginCartInfoListLast = loginCartInfoList.stream().sorted((o1, o2) -> {
            //按照更新时间
            return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
        }).collect(Collectors.toList());

        return loginCartInfoListLast;
    }

    /**
     * //修改选择状态
     * @param skuId
     * @param isChecked
     * @param userId
     */
    @Override
    public void checkCart(Long skuId, Long isChecked, String userId) {
        //获取到key
        String cartKey = getCartKey(userId);
        //从缓存中获取数据
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId);
        if (cartInfo!=null){
            //修改状态
            cartInfo.setIsChecked(isChecked.intValue());
            //再次放入缓存
            this.redisTemplate.opsForHash().put(cartKey,skuId,cartInfo);
        }

    }

    /**
     * 删除购物车
     * @param skuId
     * @param userId
     */
    @Override
    public void deleteCart(Long skuId, String userId) {
        String cartKey = getCartKey(userId);
        this.redisTemplate.opsForHash().delete(cartKey,skuId);
    }

    /***
     * 获取选中状态的购物车列表
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId.toString());
        List<CartInfo> cartInfoList = this.redisTemplate.boundHashOps(cartKey).values();  //  hvals key
        //用到了java8新特性的stream  中的过滤
        List<CartInfo> cartInfoListLast = cartInfoList.stream().filter(cartInfo -> {
            //应该获取最新的价格
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());
        return cartInfoListLast;
    }

    /**
     * 设置购物车的过期时间
     * @param cartKey
     */
    private void setCartKeyExpire(String cartKey) {
        this.redisTemplate.expire(cartKey, RedisConst.USER_CART_EXPIRE, TimeUnit.SECONDS);
    }

    /**
     * 这个方法就是获取购物车key 的！
     * @param userId
     * @return
     */
    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
